/*
 * $Id: EngineManager.java 136 2009-07-16 07:53:43Z donbeave $
 */

package labour.concept.engine.client.data;

import java.util.List;
import java.util.Map;

import labour.concept.client.data.ConceptManager;
import labour.concept.client.data.Locale;
import labour.concept.client.data.ObjectModel;
import labour.concept.client.data.ObjectType;
import labour.concept.client.data.ObjectsLoadResult;
import labour.concept.engine.client.EngineConnector;

import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.store.ListStore;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class EngineManager extends ConceptManager {

  protected Site mainSite;

  protected ListStore<Site> sitesStore;
  protected Boolean sitesLoaded = false;

  public EngineManager(EngineConnector connector) {
    super(connector);

    sitesStore = new ListStore<Site>();
  }

  public void loadSites(final AsyncCallback<List<Site>> callback) {
    getConnector().loadSites(new AsyncCallback<List<SiteModel>>() {
      public void onFailure(Throwable caught) {

      }

      public void onSuccess(List<SiteModel> result) {
        processSites(result);

        callback.onSuccess(getSites());
      }
    });
  }

  public List<Site> getSites() {
    return sitesStore.getModels();
  }

  public Site getSiteById(String id) {
    return sitesStore.findModel(SiteModel.ID, id);
  }

  public Site getSiteByName(String name) {
    return sitesStore.findModel(SiteModel.NAME, name);
  }

  public Site getMainSite() {
    return mainSite;
  }

  public void setMainSite(Site site) {
    if (defaultLocale == null) {
      setDefaultLocale(site.getLocale());
    }
    mainSite = site;
  }

  @Override
  public EngineObject createObject(ObjectType type, String name, Locale locale) {
    return (EngineObject) super.createObject(type, name, locale);
  }

  @SuppressWarnings("unchecked")
  public void loadRootObjects(Site site, final AsyncCallback callback) {
    getConnector().loadRootObjects(site.getModel().getId(), new AsyncCallback<ObjectsLoadResult<EngineObjectModel>>() {
      public void onFailure(Throwable caught) {
        callback.onFailure(caught);
      }

      public void onSuccess(ObjectsLoadResult<EngineObjectModel> result) {
        processObjects(result.getData());
        processObjectsTexts(result.getTexts());

        callback.onSuccess(getObjects(result.getData()));
      }
    });
  }

  @SuppressWarnings("unchecked")
  public void loadObjectChildren(EngineObject object, final AsyncCallback callback) {
    getConnector().loadObjectChildren(object.getModel(), new AsyncCallback<ObjectsLoadResult<EngineObjectModel>>() {
      public void onFailure(Throwable caught) {
        callback.onFailure(caught);
      }

      public void onSuccess(ObjectsLoadResult<EngineObjectModel> result) {
        processObjects(result.getData());
        processObjectsTexts(result.getTexts());

        callback.onSuccess(getObjects(result.getData()));
      }
    });
  }

  @Override
  public EngineConnector getConnector() {
    return (EngineConnector) super.getConnector();
  }

  @Override
  @SuppressWarnings("unchecked")
  protected void processBasicData(Map data) {
    super.processBasicData(data);

    List<SiteModel> sites = (List<SiteModel>) data.get("sites");

    if (!sites.isEmpty()) {
      processSites(sites);

      // TODO установка сайта по умолчанию
      setMainSite(getSites().get(0));

      sitesLoaded = true;
    }
  }

  protected void processSites(List<SiteModel> sites) {
    processIdModels(sites, sitesStore);
  }

  @Override
  protected ModelData createModel(BaseModelData model) {
    if (model instanceof SiteModel) {
      return createSite((SiteModel) model);
    }
    return super.createModel(model);
  }

  protected Site createSite(SiteModel model) {
    return new Site(model, this);
  }

  @Override
  protected EngineObject createObject(ObjectType type) {
    EngineObjectModel model = new EngineObjectModel();
    model.set(ObjectModel.TYPE_ID, type.getModel().getId());

    EngineObject object = createObject(model);

    // привязываем новый объект к текущему сайту
    object.getModel().set(EngineObjectModel.SITE_ID, getMainSite().getModel().getId());

    return object;
  }

  @Override
  protected EngineObject createObject(ObjectModel model) {
    return new EngineObject((EngineObjectModel) model, this);
  }

}
